/**

This file is part of MaCI/GIMnet.

MaCI/GIMnet is free software: you can redistribute it and/or modify it 
under the terms of the GNU Lesser General Public License as published 
by the Free Software Foundation, either version 3 of the License, or 
(at your option) any later version.

MaCI/GIMnet is distributed in the hope that it will be useful, but WITHOUT 
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public 
License for more details.

You should have received a copy of the GNU Lesser General Public 
License along with GIMnet. (See COPYING.LESSER) If not, see 
<http://www.gnu.org/licenses/>.

**/
#ifndef TGIMI_BITMAP_WITH_TIMESTAMP_H_
#define TGIMI_BITMAP_WITH_TIMESTAMP_H_

#include <string.h>
#include <assert.h>
#include <time.h>
#include <sys/time.h>
#include <inttypes.h>

/**
* This is the definition of Bitmap data for sendig it over the GIM system.
*/

//// Bitmap type definitions. 
//// NOTE IMAGE TYPES MUST MATCH TO SERVERS enum ECameraImageFormat types!!
//// defined in the TCameraImage.h
#define TGIMI_BITMAP_WITH_TIMESTAMP_TYPE_UNKNOWN	0	///< Unknown bitmaptype
#define TGIMI_BITMAP_WITH_TIMESTAMP_TYPE_RGB		1	///< RGB image bitmaptype
#define TGIMI_BITMAP_WITH_TIMESTAMP_TYPE_YUV420P	2	///<YUV420 image
#define TGIMI_BITMAP_WITH_TIMESTAMP_TYPE_YUV422		3	///<YUV422 image
#define TGIMI_BITMAP_WITH_TIMESTAMP_TYPE_JPEG		4	///<JPEG image
#define TGIMI_BITMAP_WITH_TIMESTAMP_TYPE_GRAYSCALE 5 ///<Grayscale image

#ifndef GIM_TIMESTAMP_DEFINED
#define GIM_TIMESTAMP_DEFINED
struct gim_timestamp{
	int32_t tv_sec;	   /* seconds */
	int32_t tv_usec;  /* microseconds */
};
#endif

struct TGIMI_BITMAP_WITH_TIMESTAMP_header{
public:
	gim_timestamp tim;   		///< The timestamp for the image
	int32_t datasize;			///< Size of the bitmap data in bytes
	int32_t width;				///< Width of the bitmap
	int32_t height;				///< Height of the bitmap
	unsigned char bitmap_type;	///< The type of the bitmap		
};

#define TGIMI_BITMAP_WITH_TIMESTAMP_header_size (4+4+4+4+4+1)

struct TGIMI_BITMAP_WITH_TIMESTAMP{
private:
  TGIMI_BITMAP_WITH_TIMESTAMP(const TGIMI_BITMAP_WITH_TIMESTAMP &)
    : dataBufferSize(0), 
      data(NULL),
      header(NULL),
      bitmap_data(NULL) {}
  TGIMI_BITMAP_WITH_TIMESTAMP &operator=(const TGIMI_BITMAP_WITH_TIMESTAMP &) { return *this; }
  
  int32_t dataBufferSize;	///< size of memory reserved for the *data
	unsigned char *data;	///< The whole data

	/*
	* reserves the *data 
	*/
	void allocate(int bitmap_datasize){
		if (dataBufferSize < (bitmap_datasize+TGIMI_BITMAP_WITH_TIMESTAMP_header_size)) {
	  	  if (data) free(data);
		  
		  data = (unsigned char *) 
		  	malloc( sizeof(unsigned char)*bitmap_datasize + 
			  TGIMI_BITMAP_WITH_TIMESTAMP_header_size );				
			  
		  header = (TGIMI_BITMAP_WITH_TIMESTAMP_header *) data;
		  bitmap_data = (unsigned char *) (header+1);
		  dataBufferSize = bitmap_datasize + TGIMI_BITMAP_WITH_TIMESTAMP_header_size;
		  //fprintf(stderr,"JPEG Alloc: dataBufferSize=%d, header=%d, jpegData=%d\n",dataBufferSize, TGIMI_JPEG_data_with_timestamp_header_size, jpegdatasize);
	    }
	}
	
public:
	TGIMI_BITMAP_WITH_TIMESTAMP_header *header;
	unsigned char *bitmap_data;
	
	TGIMI_BITMAP_WITH_TIMESTAMP():
		dataBufferSize(0), 
		data(NULL),
		header(NULL),
		bitmap_data(NULL) {
	}
	
	~TGIMI_BITMAP_WITH_TIMESTAMP(){
		if(data) free(data);
	}
	

	/**
	* Copy the data into *data
	* @param *img 			The  bitmap data pointer
	* @param size			The size of the bitmap data
	* @param timestamp		The timestamp =  the time the kernel grapped the image
	* @param bitmap_width	The width of the bitmap
	* @param bitmap_height 	The height of the image
	* @param bitmap_type	The type of the bitmap (see definitions from beginning of this file)
	*/
	void setBitmapData(unsigned char *img, 
						int size, 
						struct timeval timestamp,
						int32_t bitmap_width,
						int32_t bitmap_height,
						unsigned char bitmap_type){
		
		allocate(size);
		memcpy(bitmap_data, img, size);
		header->datasize = size;
		header->tim.tv_sec = (int32_t) timestamp.tv_sec;
		header->tim.tv_usec = (int32_t) timestamp.tv_usec;
		header->height = bitmap_height;
		header->width = bitmap_width;
		header->bitmap_type = bitmap_type;
		
		//fprintf(stderr,"setJPEGData:: jpegSize=%d (header=%d)\n",size,header->datasize);	
	}
	
	/**
	* Copies the data from the GIMI properly to the structure
	*/
	void handleNetPacket(const unsigned char *indata, int inDataSize){

	  TGIMI_BITMAP_WITH_TIMESTAMP_header *hdr = 
	  	(TGIMI_BITMAP_WITH_TIMESTAMP_header *) indata;
	  
	  assert(inDataSize>=TGIMI_BITMAP_WITH_TIMESTAMP_header_size);
	  
	  //fprintf(stderr,"header: %d data: %d\n",(hdr->datasize+TGIMI_JPEG_data_with_timestamp_header_size), inDataSize);
	  
	  assert((hdr->datasize+TGIMI_BITMAP_WITH_TIMESTAMP_header_size) ==  inDataSize);
	  
	  allocate(hdr->datasize); // By jpegsize
	  memcpy(data, indata, hdr->datasize+TGIMI_BITMAP_WITH_TIMESTAMP_header_size); 
	}
	
	/**
	* Returns the size of the whole data in bytes
	*/
	int size(){
		return (TGIMI_BITMAP_WITH_TIMESTAMP_header_size + header->datasize);
	}
	/**
	* Returns pointer to the whole data
	*/
	const unsigned char * getNetPacket(){
	  return data;
	}
	/**
	* Returns the timestamp of the image
	*/
	struct timeval getTimestamp(){
		struct timeval t;
		t.tv_usec = header->tim.tv_usec;
		t.tv_sec = header->tim.tv_sec;
		return t;
	}
	/**
	* Returns A Copy of the bitmap header
	*/
	TGIMI_BITMAP_WITH_TIMESTAMP_header getHeader(){
		TGIMI_BITMAP_WITH_TIMESTAMP_header head;
		
		if(header){
			memcpy(&head,header,TGIMI_BITMAP_WITH_TIMESTAMP_header_size);
		}
		
		return head;
	}
	
	void printHeader(){
		fprintf(stderr,"TGIMI_BITMAP_WITH_TIMESTAMP_header::\n");
		fprintf(stderr,"DataSize: %d\n",header->datasize);
		fprintf(stderr,"Height: %d Width: %d\n",header->height,header->width);
		fprintf(stderr,"Type: %d\n",header->bitmap_type);
		fprintf(stderr,"Time s:%d us:%d\n",header->tim.tv_sec,header->tim.tv_usec);
	}
	
	
};


#endif
